<script setup lang="ts">
import {
  NTree,
  useMessage,
  type TreeOption,
  NScrollbar,
  NForm,
  NFormItem,
  NInput,
  NTreeSelect,
  NInputNumber,
  NSelect,
  NButton,
  type FormInst,
  NSpin,
  NIcon,
  useDialog,
  NEllipsis,
  type FormItemRule
} from 'naive-ui'
import { h, onMounted, ref, shallowRef, onActivated, onUnmounted, onDeactivated } from 'vue'
import type { PositionTableRowModel, PositionModel } from '@/api/sysPosition'
import { sendRequest } from '@/utils/api'
import type { HttpResponsePagination, HttpResponse } from '@/utils/http'
import FixedAction from '@/components/FixedAction.vue'
import { ArrowForwardIosFilled } from '@vicons/material'
import type { InstitutionTreeModel } from '@/api/sysInstitution'

const message = useMessage()
const dialog = useDialog()

onUnmounted(() => {
  dialog.destroyAll()
})
onDeactivated(() => {
  dialog.destroyAll()
})

onActivated(() => {
  if (window.flags.flushPosition) {
    window.flags.flushPosition = false
    queryTable(true)
  }
})

const treeOptions = shallowRef<InstitutionTreeModel[]>([])
const treeLoading = ref(false)
const queryTreeOptions = async () => {
  try {
    treeLoading.value = true
    const [error, res] = await sendRequest<HttpResponse<InstitutionTreeModel[]>>({
      module: 'sysInstitution',
      api: 'getTree'
    })

    if (error) return message.error(error.message)
    if (res.code !== 0) return message.error(res.msg)
    treeOptions.value = res.data
  } catch (error) {
    console.log(error)
  } finally {
    treeLoading.value = false
  }
}

const renderSwitcherIcon = () => h(NIcon, null, { default: () => h(ArrowForwardIosFilled) })
const nodeProps = ({ option }: { option: TreeOption }) => {
  return {
    onClick: () => handleNodeClick(option.id as number),
    style: formData.value.id === option.id ? 'background-color: var(--n-node-color-active)' : ''
  }
}
const renderLabel = ({ option }: { option: TreeOption }) => {
  return h(
    NEllipsis,
    {
      style: 'max-width: 500rem',
      tooltip: {
        maxWidth: 500
      }
    },
    { default: () => option.positionName }
  )
}

const tableData = shallowRef<PositionTableRowModel[]>([])
const tableLoading = ref(false)
const queryTable = async (isFlush = false) => {
  try {
    tableLoading.value = true
    const [error, res] = await sendRequest<HttpResponsePagination<PositionTableRowModel>>({
      module: 'sysPosition',
      api: 'list',
      override: {
        params: {
          limit: 100000
        }
      }
    })

    if (error) return message.error(error.message)
    if (res.code !== 0) return message.error(res.msg)
    tableData.value = res.data.list
    if (!isFlush && res.data.list.length > 0) handleNodeClick(res.data.list[0].id)
  } catch (error) {
    console.log(error)
  } finally {
    tableLoading.value = false
  }
}

const formInst = shallowRef<FormInst | null>(null)
const formData = ref({} as PositionModel)
const formLoading = ref(false)
const submitLoading = ref(false)

const handleNodeClick = async (id: number) => {
  console.log('id', id)

  try {
    formLoading.value = true
    const [error, res] = await sendRequest<HttpResponse<PositionModel>>({
      module: 'sysPosition',
      api: 'info',
      uri: {
        id
      }
    })

    if (error) return message.error(error.message)
    if (res.code !== 0) return message.error(res.msg)
    formData.value = res.data
  } catch (error) {
    console.log(error)
  } finally {
    formLoading.value = false
  }
}

const handleSubmit = () => {
  formInst.value?.validate(async (error) => {
    if (error) return

    try {
      submitLoading.value = true
      const [error, res] = await sendRequest<HttpResponse>({
        module: 'sysPosition',
        api: 'update',
        override: {
          data: formData.value
        }
      })

      if (error) return message.error(error.message)
      if (res.code !== 0) message.error(res.msg)
      message.success('保存成功')
      queryTable(true)
    } catch (error) {
      message.error('保存失败')
      console.log(error)
    } finally {
      submitLoading.value = false
    }
  })
}

const deleteLoading = ref(false)
const handleDelete = () => {
  dialog.warning({
    title: '确认删除？',
    positiveText: '确认',
    negativeText: '取消',
    loading: deleteLoading.value,
    onPositiveClick: async () => {
      try {
        deleteLoading.value = true
        const [error, res] = await sendRequest<HttpResponse<PositionTableRowModel>>({
          module: 'sysPosition',
          api: 'delete',
          override: {
            data: [formData.value.id]
          }
        })

        if (error) return message.error(error.message)
        if (res.code !== 0) return message.error(res.msg)
        queryTable()
      } catch (error) {
        console.log(error)
      } finally {
        deleteLoading.value = false
      }
    }
  })
}

const limitRule: FormItemRule = {
  trigger: ['blur', 'input'],
  validator: (_, value) => {
    return value ? value.length <= 100 : true
  },
  message: '字符长度不能大于100'
}

onMounted(() => {
  queryTable()
  queryTreeOptions()
})
</script>

<template>
  <div class="position">
    <div class="position-header">请选择增加或选择您要编辑的职位</div>

    <div class="position-content">
      <div class="position-tree">
        <div class="position-tree__header">名称</div>
        <NScrollbar style="height: calc(100% - 28rem)">
          <NSpin :show="tableLoading">
            <NTree
              :data="(tableData as unknown as TreeOption[])"
              :node-props="nodeProps"
              :render-label="renderLabel"
              key-field="id"
              default-expand-all
              label-field="positionName"
              block-line
              :render-switcher-icon="renderSwitcherIcon"
            />
          </NSpin>
        </NScrollbar>
      </div>

      <div class="position-form">
        <NSpin :show="formLoading">
          <NForm
            :disabled="submitLoading"
            :model="formData"
            ref="formInst"
            label-placement="left"
            require-mark-placement="left"
            label-width="100rem"
          >
            <NFormItem
              label="名称："
              path="positionName"
              :rule="[{ required: true, message: '名称为必填项，请输入名称' }, limitRule]"
            >
              <NInput
                placeholder="请输入"
                v-model:value="formData.positionName"
              />
            </NFormItem>
            <NFormItem
              label="所属部门："
              path="deptIdList"
              :rule="{
                required: true,
                message: '所属部门为必填项，请选择上级部门',
                type: 'array'
              }"
            >
              <NTreeSelect
                multiple
                :loading="treeLoading"
                v-model:value="formData.deptIdList"
                :options="(treeOptions as unknown as TreeOption[])"
                key-field="id"
                default-expand-all
                label-field="name"
                block-line
                placeholder="请选择"
              />
            </NFormItem>
            <NFormItem label="排序：">
              <NInputNumber
                :value="formData.sortIndex"
                @update:value="
                  (e) => (Number.isFinite(e) ? (formData.sortIndex = e as number) : Number.MAX_SAFE_INTEGER)
                "
                style="flex: 1"
                placeholder="请输入"
                :show-button="false"
              />
            </NFormItem>
            <NFormItem
              label="状态："
              path="positionStatus"
              :rule="{ required: true, message: '状态为必填项，请选择状态', type: 'number' }"
            >
              <NSelect
                v-model:value="formData.positionStatus"
                :options="[
                  { label: '启用', value: 1 },
                  { label: '禁用', value: 0 }
                ]"
                placeholder="请选择"
              />
            </NFormItem>
            <!-- <span style="padding-left: 100rem">
              带
              <span style="color: #fd4a29">*</span>
              为必填项
            </span> -->
          </NForm>
        </NSpin>
      </div>
    </div>
  </div>

  <FixedAction>
    <div class="position-buttons">
      <NButton
        color="#5FAAB1"
        @click="$router.push($route.fullPath + '/add')"
      >
        新增
      </NButton>
      <NButton
        color="#5FB17F"
        :disabled="submitLoading || formLoading"
        :loading="submitLoading"
        @click="handleSubmit"
      >
        保存
      </NButton>
      <NButton
        color="#D9534F"
        :disabled="formLoading || deleteLoading"
        @click="handleDelete"
      >
        删除
      </NButton>
    </div>
  </FixedAction>
</template>

<style scoped lang="scss">
.position {
  display: flex;
  flex-direction: column;
  height: 100%;
  color: rgba(0, 0, 0, 0.85);
}

.position-header {
  padding: 24rem 36rem 20rem;
  font-size: 16rem;
  border-bottom: 1px solid #ffffff;
}

.position-content {
  display: flex;
  height: calc(100% - 100rem - 72rem);
  gap: 0 20rem;
  padding: 20rem;
}

.position-tree {
  min-width: 38%;
  height: 100%;
  padding: 23rem 31rem;
  background-color: #ebeceb;

  &__header {
    height: 28rem;
    line-height: 28rem;
    font-size: 20rem;
    margin-bottom: 20rem;
  }
}

.position-form {
  flex: 1;
  height: 100%;
  padding: 33rem 26rem 33rem 16rem;
  background-color: #ebeceb;
}

.position-buttons {
  display: flex;
  justify-content: center;
  gap: 0 16rem;

  .n-button {
    width: 100rem;
    height: 50rem;
  }
}
</style>
